package com.jrx.anytxn.param.service.merge.impl;

import com.jrx.anytxn.common.exception.TxnBadGatewayException;
import com.jrx.anytxn.common.uitl.*;
import com.jrx.anytxn.feign.common.GateWayPredicate;
import com.jrx.anytxn.feign.gateway.bean.TransDetl;
import com.jrx.anytxn.feign.gateway.request.CoreRequest11;
import com.jrx.anytxn.feign.gateway.request.CoreRequest12;
import com.jrx.anytxn.feign.gateway.response.CoreResponse11;
import com.jrx.anytxn.feign.gateway.response.CoreResponse12;
import com.jrx.anytxn.feign.gateway.service.IInnerGatewayService;
import com.jrx.anytxn.number.exception.SegmentException;
import com.jrx.anytxn.number.service.ISegmentService;
import com.jrx.anytxn.param.constant.Constant;
import com.jrx.anytxn.param.constant.ErrorMsgConstant;
import com.jrx.anytxn.param.entity.GaSubjectTable;
import com.jrx.anytxn.param.entity.PrOrganizationTable;
import com.jrx.anytxn.param.entity.TlMergeBillingDetlLog;
import com.jrx.anytxn.param.entity.TlMergeBillingSummaryLog;
import com.jrx.anytxn.param.mapper.ext.ExtPrOrganizationTableMapper;
import com.jrx.anytxn.param.mapper.ext.ExtSubjectTableMapper;
import com.jrx.anytxn.param.service.merge.IMergeBillingLogService;
import com.jrx.anytxn.param.service.merge.IMergeBillingService;
import com.jrx.anytxn.param.service.merge.bean.MergeFile;
import com.jrx.anytxn.param.service.merge.bean.MergeFileSortDto;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @program: anytxn-cf-parent
 * @description:
 * @author: xiaoyu.jing
 * @date: 2020-11-06 17:10
 **/
@Service
public class MergeBillingServiceImpl implements IMergeBillingService {

    Logger logger = LoggerFactory.getLogger(this.getClass());


    @Resource
    private ExtSubjectTableMapper extSubjectTableMapper;

    @Resource
    private ExtPrOrganizationTableMapper extPrOrganizationTableMapper;

    @Autowired
    private RedisTemplate<String, Object> template;

    @Autowired
    private ISegmentService segmentService;

    @Autowired
    private IMergeBillingLogService mergeBillingLogService;

    @Lazy
    @Autowired
    private IInnerGatewayService innerGatewayService;


    @Override
    public void dealMergeBilling(List<MergeFile> mergeFileList) throws Exception {
        PrOrganizationTable org = extPrOrganizationTableMapper.selectByOrgIdForBatch(Constant.DEFAULT_ORG_NUMBER);
        Date today = org.getToday();
        Function<MergeFile, MergeFileSortDto> transSort = detail -> {
            MergeFileSortDto sortDto = new MergeFileSortDto();
            GaSubjectTable subjectTable = extSubjectTableMapper.selectBySubjectIdAndTenId(detail.getTenantId(), detail.getSubjectId());
            sortDto.setMergeFile(detail);
            sortDto.setSubjectTable(subjectTable);
            if(detail.getSign().equals(subjectTable.getBalDirection())){
                sortDto.setPriority(0);
            }else{
                sortDto.setPriority(1);
            }
            return sortDto;
        };

        //按科目顺序排序
        mergeFileList = mergeFileList.stream()
                .map(transSort)
                .sorted(Comparator.comparingInt(MergeFileSortDto::getPriority))
                .map(MergeFileSortDto::getMergeFile)
                .collect(Collectors.toList());


        //分别计算出贷记，借记总金额
        BigDecimal creditAmt = mergeFileList.stream().filter(sort ->"C".equals(sort.getSign()))
                .map(MergeFile::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal debtAmt = mergeFileList.stream().filter(sort ->"D".equals(sort.getSign()))
                .map(MergeFile::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        logger.info("贷记金额:{},借记金额:{}", creditAmt, debtAmt);

        //生成明细
        String detlSeqNo = Constant.MERGE_BILLING_SEQ_PREFIX.concat(SeqUtils.getSNByLength(Constant.TRANSFER_LOG_SEQ_RADOM_LENGTH));
        int i = 1;
        List<TransDetl> detlList = new ArrayList<>();
        List<TlMergeBillingDetlLog> detlLogList = new ArrayList<>();
        for (MergeFile mergeFile : mergeFileList) {
            if (mergeFile.getAmount().compareTo(BigDecimal.ZERO) != 0) {
                this.dealDelt(detlList,detlLogList,mergeFile,org,detlSeqNo,i);
                i++;
            }
        }


        if (CollectionUtils.isEmpty(detlList)) {
            logger.info("今日并账的科目金额为0");
            return;
        }

        String key = Constant.MERGE_BILLING_REDIS_KEY.concat(org.getTenantId());
        ValueOperations<String, Object> redis = template.opsForValue();
        Object obj = redis.get(key);
        if (null == obj) {
            obj = 0;

        }
        Integer nextInt = (Integer) obj + 1;
        // SET key value: 设置指定 key 的值
        String vchNo = SeqUtils.generateSeqNo(nextInt);
        redis.set(key, nextInt, 72L, TimeUnit.HOURS);


        //构建汇总流水日志
        CoreRequest11 coreRequest11 = this.buildSum(org,vchNo,debtAmt,creditAmt,i);
        TlMergeBillingSummaryLog summaryLog = new TlMergeBillingSummaryLog();
        BeanMapping.copy(coreRequest11, summaryLog);
        summaryLog.setId(segmentService.getId(Constant.TL_MERGE_BILLING_SUMMARY_LOG_ID));
        summaryLog.setRecordVersionNumber(Constant.VERSION_NUMBER);
        summaryLog.setBusinessDate(DateUtils.parseDate(coreRequest11.getBusDate(),DateUtils.DATE_PATTERN_ANOTHER));
        summaryLog.setSeqNo(coreRequest11.getServiceSeq());
        summaryLog.setOrganizationId(org.getOrganizationId());
        summaryLog.setVchNum(coreRequest11.getVchNum());
        summaryLog.setVchMaxNo(coreRequest11.getVchMaxNo());
        summaryLog.setUpdateBy(Constant.SYS_OPRATE);
        mergeBillingLogService.saveSummaryLog(summaryLog);


        GateWayPredicate<CoreResponse11> mergeSum = () -> innerGatewayService.mergeBillSum(JsonUtils.toJSon(coreRequest11));
        CoreResponse11 mergeSumRes = mergeSum.getRes(mergeSum);
        if (null == mergeSumRes ) {
            summaryLog.setDealState("F");
            summaryLog.setBusMsg("调用网关失败");
            mergeBillingLogService.updateSummaryLog(summaryLog);
            throw new TxnBadGatewayException(ErrorMsgConstant.GATEWAY_ERROR);
        }
        summaryLog.setBusCode(mergeSumRes.getBusCode());
        summaryLog.setBusMsg(mergeSumRes.getBusMsg());
        summaryLog.setDealState(mergeSumRes.getDealState());
        summaryLog.setDealResult(mergeSumRes.getDealResult());
        mergeBillingLogService.updateSummaryLog(summaryLog);

        detlLogList.forEach(detlLog -> detlLog.setVchNo(vchNo));
        mergeBillingLogService.saveDetlLogList(detlLogList);

        CoreRequest12 coreRequest12 = this.buildDetl(detlList,org,detlSeqNo,vchNo,i);
        GateWayPredicate<CoreResponse12> mergeDetl = () -> innerGatewayService.mergeBillDetl(JsonUtils.toJSon(coreRequest12));
        CoreResponse12 mergeDetlRes = mergeDetl.getRes(mergeDetl);
        if (null == mergeDetlRes ) {
            detlLogList.forEach(
                    detlLog -> {
                        detlLog.setDealState("F");
                        detlLog.setBusMsg("调用网关失败");
                    });
            mergeBillingLogService.updateDetlLogList(detlLogList);
            throw new TxnBadGatewayException(ErrorMsgConstant.GATEWAY_ERROR);
        }
        detlLogList.forEach(
                detlLog -> {
                    detlLog.setBusCode(mergeDetlRes.getBusCode());
                    detlLog.setBusMsg(mergeDetlRes.getBusMsg());
                    detlLog.setDealState(mergeDetlRes.getDealState());
                    detlLog.setDealResult(mergeDetlRes.getDealResult());
                });
        mergeBillingLogService.updateDetlLogList(detlLogList);
    }

    /**
     *
     * @param detlList
     * @param detlLogList
     * @param mergeFile
     * @param org
     * @param detlSeqNo
     * @param i
     * @throws SegmentException
     */
    private void dealDelt(List<TransDetl> detlList,List<TlMergeBillingDetlLog> detlLogList, MergeFile mergeFile ,
                          PrOrganizationTable org,String detlSeqNo,int i) throws SegmentException {
        TransDetl detl = new TransDetl();
        detl.setAcctNo(mergeFile.getSubjectId());
        String dcFlag = mergeFile.getSign();
        detl.setDcFlag(dcFlag);
        detl.setTotalAmnt(mergeFile.getAmount());
        detl.setVchNum(i);
        detl.setVchSen(i);
        //暂时处理为不涉税
        if(StringUtils.isNotBlank(mergeFile.getPriceTxaCode())) {
            detl.setTaxFlag(Constant.TAX_FLAG_Y);
            detl.setTaxCode(mergeFile.getPriceTxaCode());
            detl.setTaxSubCode(Constant.TAX_SUB_CODE_00);
            //泰安银行的处理方式
            if(Constant.TENANT_ID_TA.equals(mergeFile.getTenantId())) {
                detl.setSplitTaxFlag(Constant.SPLIT_TAX_FLAG_Y);
            }else if(Constant.TENANT_ID_LS.equals(mergeFile.getTenantId())){
                //临商银行的处理方式
                detl.setTaxRate(BigDecimal.valueOf(0.06));
                detl.setSalesAmt(mergeFile.getSalesAmt());
                detl.setRcvdFlag(Constant.RCVD_FLAG_0);
            }
        }else{
            detl.setTaxFlag(Constant.TAX_FLAG_N);
        }

        detlList.add(detl);


        //构建明细请求流水日志
        TlMergeBillingDetlLog detlLog = new TlMergeBillingDetlLog();
        BeanMapping.copy(detl,detlLog);
        detlLog.setId(segmentService.getId(Constant.TL_MERGE_BILLING_DETL_LOG_ID));
        detlLog.setTenantId(org.getTenantId());
        detlLog.setBusinessDate(org.getToday());
        detlLog.setVchNum(i);
        detlLog.setVchSen(i);
        detlLog.setSeqNo(detlSeqNo);
        detlLog.setOrganizationId(org.getOrganizationId());
        detlLog.setVchChannelType(Constant.VCH_CHNL_TYP_68);
        detlLog.setVchTrType(Constant.VCH_TX_TYP_01);
        detlLog.setRecordVersionNumber(Constant.VERSION_NUMBER);
        detlLog.setUpdateBy(Constant.SYS_OPRATE);
        detlLogList.add(detlLog);

    }

    /**
     * 构建汇总并账请求
     * @param org
     * @param vchNo
     * @param debtAmt
     * @param creditAmt
     * @param i
     * @return
     * @throws SocketException
     */
    private CoreRequest11 buildSum(PrOrganizationTable org,String vchNo,BigDecimal debtAmt, BigDecimal creditAmt,int i) throws SocketException {
        String summarySeqNo = Constant.MERGE_BILLING_SEQ_PREFIX.concat(SeqUtils.getSNByLength(Constant.TRANSFER_LOG_SEQ_RADOM_LENGTH));
        //构建汇总请求流水
        CoreRequest11 coreRequest11 = new CoreRequest11();
        coreRequest11.setServiceId(Constant.GATEWAY_SERVICE_ID); // 请求系统Id
        coreRequest11.setServiceIp(InternetUtils.getLocalIp()); // 请求ip地址
        coreRequest11.setTenantId(org.getTenantId()); // 租户Id
        coreRequest11.setServiceSeq(summarySeqNo);
        coreRequest11.setBusDate(DateUtils.formatDate2(org.getToday()));
        coreRequest11.setVchNo(vchNo);
        coreRequest11.setVchNum(i-1);
        coreRequest11.setVchStatus(Constant.TOT_SLIP_STS_1);
        coreRequest11.setdTotalAmnt(debtAmt);
        coreRequest11.setcTotalAmnt(creditAmt);
        coreRequest11.setVchMaxNo(i-1);
        coreRequest11.setTransType(Constant.TX_TYP_1);
        coreRequest11.setVchChannelType(Constant.VCH_CHNL_TYP_68);
        return coreRequest11;
    }

    /**
     * 构建汇总明细请求
     * @param detlList
     * @param org
     * @param detlSeqNo
     * @param vchNo
     * @param i
     * @return
     * @throws SocketException
     */
    private CoreRequest12 buildDetl(List<TransDetl> detlList, PrOrganizationTable org,String detlSeqNo,String vchNo,int i) throws SocketException {
        //构建明细请求流水
        CoreRequest12 coreRequest12 = new CoreRequest12();
        coreRequest12.setServiceId(Constant.GATEWAY_SERVICE_ID); // 请求系统Id
        coreRequest12.setServiceIp(InternetUtils.getLocalIp()); // 请求ip地址
        coreRequest12.setTenantId(org.getTenantId()); // 租户Id
        coreRequest12.setServiceSeq(detlSeqNo);
        coreRequest12.setBusDate(DateUtils.formatDate2(org.getToday()));
        coreRequest12.setPreBusDate(DateUtils.formatDate2(org.getLastProcessingDate()));
        coreRequest12.setVchChannelType(Constant.VCH_CHNL_TYP_68);
        coreRequest12.setVchTrType(Constant.VCH_TX_TYP_01);
        coreRequest12.setVchNo(vchNo);
        coreRequest12.setTransList(detlList);
        return coreRequest12;
    }
}
